import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;


public class SumSinCal {
    private int upperBound;
    private int lowerBound;
    private int nThreads;
    private long time;
    //----------------------------------------------------------------------
    public SumSinCal(int upperBound, int lowerBound) {
        this.upperBound = upperBound;
        this.lowerBound = lowerBound;
        this.nThreads = nThreads;
    }
    //----------------------------------------------------------------------
    public double calculete() {
        time = System.currentTimeMillis();          //Dimension of time and start the timers
        //System.nanoTime();                        //Work of the method depends on the platform and power PC
        double result = 0.0;

        ExecutorService pool = Executors.newFixedThreadPool(nThreads);
        Set<Future<Double>> thr = new HashSet<Future<Double>>();

        int distance = (int) ((Math.abs(upperBound-lowerBound)) / nThreads);
        for (int i = 0; i < nThreads; i++) {
            Callable<Double> current;
            if (i == nThreads - 1 && nThreads != 1) {
                current = new SumSin(lowerBound + distance * i + 1, upperBound+1);
            } else if (i == nThreads - 1 && nThreads == 1) {
                current = new SumSin(lowerBound + distance * i, upperBound+1);
            } else if (i == 0) {
                current = new SumSin(lowerBound + distance * i,
                        lowerBound + distance * (i + 1));
            } else {
                current = new SumSin(lowerBound + distance * i + 1,
                        lowerBound + distance * (i + 1));
            }
            Future<Double> future = pool.submit(current);
            thr.add(future);
        }
        for (Future<Double> future : thr) {
            try {
                result += future.get().doubleValue();
            } catch (InterruptedException ex) {
                Logger.getLogger(SumSinCal.class.getName()).log(Level.SEVERE, null, ex);
            } catch (ExecutionException ex) {
                Logger.getLogger(SumSinCal.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
        time = System.currentTimeMillis() - time;
        pool.shutdown();;
        return result;
    }
    public long getTimeCalculete() {
        return time;
    }
}
